home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 40
/
Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso
/
Aminet
/
mus
/
play
/
DeliDecrunch.lha
/
src
/
Decruncher.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-10-15
|
8KB
|
216 lines
/* DeliDecruncher (C) 2000 Stuart Caie <kyzer@4u.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <dos/dosextens.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <libraries/xadmaster.h>
#include <libraries/xfdmaster.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/xadmaster.h>
#include <proto/xfdmaster.h>
#include "DeliPlayer.h"
static const char version[] = "$VER: Decruncher 2.1 (15.10.2000)";
static char TempFile[] = "T:DeliDecr.dat";
static const char MatchStr[] = "~(#?displayme#?|#?readme#?|#?liesmich#?|"
"#?.diz|#?.info|#?.doc|#?.dok|#?.txt|#?.text|#?.exe|#?.lst)";
/* tries to allocate memory for and load a file, writes filelen to *lenptr */
APTR LoadFile(STRPTR filename, LONG *lenptr, ULONG memflags, DELIBASE) {
struct DosLibrary *DOSBase = DeliBase->dtg_DOSBase;
struct FileInfoBlock *fib;
APTR file = NULL, mem;
BPTR lock, fh;
LONG len;
/* lots of code just to find out file size... */
if ((fib = (struct FileInfoBlock *)
AllocDosObject(DOS_FIB, NULL))) {
if ((lock = Lock(filename, SHARED_LOCK))) {
if (Examine(lock, fib) && fib->fib_DirEntryType < 0) {
len = fib->fib_Size;
/* allocate enough memory with requested flags. */
/* if that fails, just use any public memory */
mem = AllocListData((ULONG) len, memflags);
if (!mem) mem = AllocListData((ULONG) len, MEMF_ANY | MEMF_PUBLIC);
if (mem) {
/* read in the file */
if ((fh = OpenFromLock(lock))) {
if (Read(fh, mem, len) >= 0) {
file = mem;
mem = NULL;
*lenptr = len;
}
Close(fh);
}
if (mem) FreeListData(mem);
}
}
UnLock(lock);
}
FreeDosObject(DOS_FIB, (APTR) fib);
}
return file;
}
/* This performs the decrunching of a file for DeliTracker.
* - Deli loads 1kb of the file (full filename in dtg_PathArrayPtr), this
* 1kb is shown by dtg_CheckData and dtg_CheckSize
* - the decruncher examines it, allocates memory WITH dtg_AllocListData()
* - the decruncher frees all memory and returns 1 for failure/unknown format
* - the decruncher doesn't free the actual mod's memory, but frees all
* others, and returns 0 for a successful recognition and decrunch
*/
ULONG Decrunch(DELIBASE) {
struct ExecBase *SysBase = *((struct ExecBase **) 4UL);
struct DosLibrary *DOSBase = DeliBase->dtg_DOSBase;
struct xadArchiveInfo *xai;
struct xadFileInfo *chosen, *xfi;
struct xadMasterBase *xadMasterBase;
struct xfdBufferInfo *xbi;
struct xfdMasterBase *xfdMasterBase;
UBYTE patbuf[sizeof(MatchStr)*2+2];
struct TagItem tags[3];
ULONG len, err=1;
APTR buf;
BPTR fh;
/* just in case the tempfile already exists, try to delete it */
SetProtection(TempFile, 0);
DeleteFile(TempFile);
/* try to open xadmaster, to see if the file is an archive */
if ((xadMasterBase = (struct xadMasterBase *)
OpenLibrary(XADNAME, 4))) {
if ((xai = (struct xadArchiveInfo *)
xadAllocObjectA(XADOBJ_ARCHIVEINFO, NULL))) {
/* examine file - is it an archive? */
tags[0].ti_Tag = XAD_INFILENAME;
tags[0].ti_Data = (ULONG) DeliBase->dtg_PathArrayPtr;
tags[1].ti_Tag = TAG_DONE;
if (!xadGetInfoA(xai, tags)) {
/* yes, this is an archive. Now, see if there are any files in the
* archive that fit a certain filename criteria (ie not *.txt, etc)
* and 'choose' the first acceptable file.
*/
chosen = NULL;
ParsePatternNoCase((STRPTR) MatchStr, patbuf, sizeof(patbuf));
for (xfi = xai->xai_FileInfo; (xfi); xfi = xfi->xfi_Next) {
if (MatchPatternNoCase(patbuf, FilePart(xfi->xfi_FileName))) {
chosen = xfi; break;
}
}
/* if an acceptable file was found, try to extract it */
if (chosen) {
tags[0].ti_Tag = XAD_ENTRYNUMBER;
tags[0].ti_Data = (ULONG) chosen->xfi_EntryNumber;
tags[1].ti_Tag = XAD_OUTFILENAME;
tags[1].ti_Data = (ULONG) TempFile;
tags[2].ti_Tag = TAG_DONE;
/* err=0 on success, <>0 on error */
err = xadFileUnArcA(xai, tags);
}
xadFreeInfo(xai);
}
xadFreeObjectA(xai, NULL);
}
CloseLibrary((APTR) xadMasterBase);
}
/* as file isn't an archive (or no XAD is present), let's try to decrunch
* it with XFD...
*/
if (err) {
if ((xfdMasterBase = (struct xfdMasterBase *)
OpenLibrary(XFDM_NAME, 36))) {
if ((xbi = (struct xfdBufferInfo *)
xfdAllocObject(XFDOBJ_BUFFERINFO))) {
/* try to load the full file */
if ((buf = LoadFile(DeliBase->dtg_PathArrayPtr,
&len, MEMF_PUBLIC, DeliBase))) {
xbi->xfdbi_SourceBuffer = buf;
xbi->xfdbi_SourceBufLen = len;
xbi->xfdbi_Flags = XFDFF_RECOGEXTERN;
/* if we recognize the format, and it isn't encrypted... */
if (xfdRecogBuffer(xbi) && (xbi->xfdbi_PackerFlags &
(XFDPFF_PASSWORD|XFDPFF_KEY16|XFDPFF_KEY32)) == 0) {
/* ...decrunch it */
xbi->xfdbi_TargetBufMemType = MEMF_ANY;
if (xfdDecrunchBuffer(xbi)) {
/* decrunching was successful. try to write to the tempfile */
if ((fh = Open(TempFile, MODE_NEWFILE))) {
err = (Write(fh, xbi->xfdbi_TargetBuffer,
xbi->xfdbi_TargetBufSaveLen) < 0);
Close(fh);
}
FreeMem(xbi->xfdbi_TargetBuffer, xbi->xfdbi_TargetBufLen);
}
}
FreeListData(buf);
}
xfdFreeObject((APTR) xbi);
}
CloseLibrary((APTR) xadMasterBase);
}
}
if (!err) {
/* now ensure the file is both readable and deletable */
SetProtection(TempFile, 0);
/* try to read in the file */
err = (LoadFile(TempFile, &len, MEMF_PUBLIC|MEMF_CHIP, DeliBase) == NULL);
/* delete the file, in any instance */
DeleteFile(TempFile);
}
return err;
}
const struct TagItem PlayerTags[] = {
{ DTP_RequestDTVersion, 17 },
{ DTP_PlayerVersion, (2<<16)|(1) },
{ DTP_PlayerName, (ULONG) "Decruncher" },
{ DTP_Creator, (ULONG) "written by Kyzer/CSG <kyzer@4u.net>,\n"
"XAD by Dirk Stöcker and others,\n"
"XFD by Georg Hörmann and others" },
{ DTP_Description, (ULONG) "this genie decrunches compressed mods\n"
"using the XAD dearchiving library and\n"
"the XFD decrunching library" },
{ DTP_Decrunch, (ULONG) Decrunch },
{ TAG_DONE, 0 }
};